<template>
	<view class="page-library">
		<!-- 导航栏 -->
		<u-navbar placeholder title="" :autoBack="false">
			<view slot="left" class="flex-align-center logo">
				<image src="https://shaanxikefeng.com/static/picture/logo-white.png" mode="heightFix" style="height: 40rpx;"></image>
				<!-- <view class="">页面库</view> -->
			</view>
			<view slot="right" class="nav-right-btns">
				<!-- 目录授权状态 -->
				<view class="auth-status" @click="handleAuthClick" v-if="isFileSystemSupported">
					<text class="status-text">{{ projectDirHandle ? '已授权' : '未授权' }}</text>
				</view>
				<!-- 新增分类按钮 -->
				<view class="edit-btn" :class="{ disabled: !projectDirHandle }" @click="handleAddCategoryClick">
					<text class="edit-text">新增分类</text>
				</view>
				<!-- 编辑按钮 -->
				<view class="edit-btn" :class="{ disabled: !projectDirHandle }" @click="handleEditClick">
					<text class="edit-text">{{ isEditMode ? '完成' : '编辑' }}</text>
				</view>
				<!-- 添加按钮 -->
				<view class="add-btn" :class="{ disabled: !projectDirHandle }" @click="handleAddPageClick">
					<text class="add-text">添加页面</text>
				</view>
			</view>
		</u-navbar>

		<view class="content-wrapper">
			<!-- 左侧分类列表 -->
			<view class="category-sidebar">
				<scroll-view scroll-y class="category-scroll">
					<view v-for="(category, index) in categories" :key="category.id"
						:class="['category-item', { active: currentCategoryId === category.id }]">
						<!-- 分类内容 -->
						<view class="category-content" @click="selectCategory(category.id)">
							<text class="category-name">
								{{ category.name }}
								<text class="count-text" v-if="getCategoryPageCount(category.id) > 0">
									({{ getCategoryPageCount(category.id) }})
								</text>
							</text>
						</view>
						<!-- 删除按钮（仅编辑模式显示） -->
						<view class="delete-category-btn" 
							@click.stop="confirmDeleteCategory(category)" 
							v-if="isEditMode">
							<u-icon name="close" size="12" color="#999"></u-icon>
						</view>
					</view>
				</scroll-view>
			</view>

			<!-- 右侧页面列表 -->
			<view class="page-list-wrapper">
				<scroll-view scroll-y class="page-scroll">
					<view v-if="currentPages.length === 0" class="empty-state">
						<u-icon name="file-text" size="60" color="#ccc"></u-icon>
						<text class="empty-text">暂无页面</text>
						<view class="add-btn-wrapper">
							<u-button type="primary" size="small" @click="showUploadPopup = true">添加页面</u-button>
						</view>
					</view>
					
					<view v-else class="page-grid">
						<view v-for="(page, index) in currentPages" :key="page.id" class="page-card">
							<!-- 页面效果图 -->
							<view class="screenshot-wrapper">
								<image :src="page.screenshot" mode="aspectFit" class="screenshot-image"></image>
							</view>
							
							<!-- 页面名称 -->
							<view class="page-name-section">
								<text class="page-name">{{ page.name }}</text>
								<text class="page-file-name">{{ page.fileName }}</text>
							</view>
							
							<!-- 操作按钮 -->
							<view class="action-buttons">
								<view class="action-btn view-code-btn" @click="viewCode(page)">
									<u-icon name="eye" size="16" color="#fff"></u-icon>
									<text>查看代码</text>
								</view>
								<view class="action-btn copy-path-btn" @click="copyPath(page)">
									<u-icon name="folder" size="16" color="#fff"></u-icon>
									<text>复制路径</text>
								</view>
							</view>
							
							<!-- 删除按钮（仅编辑模式显示） -->
							<view class="delete-btn" @click="deletePage(page, index)" v-if="isEditMode">
								<u-icon name="close-circle-fill" size="20" color="#ff4d4f"></u-icon>
							</view>
						</view>
					</view>
				</scroll-view>
			</view>
		</view>

		<!-- 上传页面弹窗 -->
		<u-popup :show="showUploadPopup" @close="showUploadPopup = false" mode="center" border-radius="10">
			<view class="upload-popup">
				<view class="popup-header">
					<text class="popup-title">添加页面</text>
					<u-icon name="close" size="20" @click="showUploadPopup = false"></u-icon>
				</view>
				
				<view class="popup-content">
					<!-- 授权提示 -->
					<view class="auth-tip" v-if="isFileSystemSupported && !projectDirHandle">
						<u-icon name="info-circle" size="16" color="#faad14"></u-icon>
						<text class="tip-text">点击右上角文件夹图标授权目录，提交时将自动创建本地文件</text>
					</view>
					
					<view class="auth-tip success" v-if="isFileSystemSupported && projectDirHandle">
						<u-icon name="checkmark-circle-fill" size="16" color="#52c41a"></u-icon>
						<text class="tip-text">已授权，提交时将自动在本地创建文件</text>
					</view>
					
					<!-- 页面名称 -->
					<view class="form-item">
						<text class="form-label">页面名称</text>
						<input class="form-input" v-model="newPage.name" placeholder="请输入页面名称" />
					</view>
					
					<!-- 页面描述 -->
					<view class="form-item">
						<text class="form-label">页面描述</text>
						<textarea class="form-textarea" v-model="newPage.description" placeholder="请输入页面描述（可选）" />
					</view>
					
					<!-- 选择分类 -->
					<view class="form-item">
						<text class="form-label">选择分类</text>
						<view class="category-selector" @click="openCategorySelector">
							<text :class="['selector-text', { placeholder: !newPage.categoryId }]">
								{{ selectedCategoryName || '请选择分类' }}
							</text>
							<u-icon name="arrow-right" size="16" color="#999"></u-icon>
						</view>
					</view>
					
					<!-- 分类列表弹窗（内嵌在上传弹窗内） -->
					<view v-if="showCategoryList" class="category-list-overlay" @click="showCategoryList = false">
						<view class="category-list-content" @click.stop>
							<view class="category-list-header">
								<text class="category-list-title">选择分类</text>
								<u-icon name="close" size="20" @click="showCategoryList = false"></u-icon>
							</view>
							<scroll-view scroll-y class="category-list-scroll">
								<view v-for="(category, index) in categories" :key="category.id" 
									class="category-list-item"
									@click="selectCategoryFromList(category)">
									<text class="category-list-name">{{ category.name }}</text>
									<u-icon v-if="newPage.categoryId === category.id" 
										name="checkmark" size="18" color="#DB0000"></u-icon>
								</view>
							</scroll-view>
							<!-- 新增分类按钮 -->
							<view class="add-category-btn" @click="showAddCategoryDialog">
								<u-icon name="plus-circle" size="18" color="#DB0000"></u-icon>
								<text class="add-category-text">新增分类</text>
							</view>
						</view>
					</view>
					
					<!-- 上传效果图 -->
					<view class="form-item">
						<text class="form-label">效果图</text>
						<view class="upload-wrapper">
							<u-upload :fileList="screenshotList" @afterRead="afterReadScreenshot" @delete="deleteScreenshot"
								name="screenshot" :maxCount="1" accept="image">
							</u-upload>
						</view>
					</view>
					
					<!-- 文件名称（英文） -->
					<view class="form-item">
						<text class="form-label">文件名称</text>
						<view class="file-name-input-wrapper">
							<input class="file-name-input" v-model="newPage.customFileName" 
								placeholder="例如：login-wechat" 
								maxlength="50"
								@input="validateFileName" />
							<text class="file-extension">.vue</text>
						</view>
						<text class="form-tip">仅支持英文字母、数字、下划线、短横线</text>
						<text class="form-tip warning" v-if="fileNameExists">
							⚠️ 文件名已存在，提交时将自动添加索引（如：文件名_1.vue）
						</text>
					</view>
					
					<!-- 上传页面代码 -->
					<view class="form-item">
						<text class="form-label">页面代码</text>
						<view class="code-upload-btn" @click="chooseCodeFile">
							<u-icon name="file-text" size="20" color="#DB0000"></u-icon>
							<text class="code-file-name" v-if="newPage.code">已选择文件（{{ codeFileSize }}）</text>
							<text class="placeholder-text" v-else>点击选择.vue文件</text>
						</view>
						<text class="form-tip" v-if="originalFileName">原文件名：{{ originalFileName }}</text>
					</view>
				</view>
				
				<view class="popup-footer">
					<u-button @click="showUploadPopup = false" size="medium" plain>取消</u-button>
					<u-button type="primary" @click="submitNewPage" size="medium" :loading="uploading">提交</u-button>
				</view>
			</view>
		</u-popup>

		<!-- 分类选择器 -->
		<u-picker :show="showCategoryPicker" @close="showCategoryPicker = false" mode="selector" :range="categories" range-key="name"
			@confirm="onCategoryConfirm"></u-picker>
		
		<!-- 新增分类弹窗 -->
		<u-popup :show="showAddCategory" @close="showAddCategory = false" mode="center" border-radius="10">
			<view class="add-category-popup">
				<view class="popup-header">
					<text class="popup-title">新增分类</text>
					<u-icon name="close" size="20" @click="showAddCategory = false"></u-icon>
				</view>
				
				<view class="popup-content">
					<!-- 分类名称 -->
					<view class="form-item">
						<text class="form-label">分类名称</text>
						<input class="form-input" v-model="newCategory.name" placeholder="例如：支付相关" maxlength="20" />
						<text class="form-tip">用于显示的中文名称</text>
					</view>
					
					<!-- 分类英文名称 -->
					<view class="form-item">
						<text class="form-label">英文名称（文件夹名）</text>
						<input class="form-input" v-model="newCategory.id" placeholder="例如：payment" maxlength="30" 
							@input="validateEnglishName" />
						<text class="form-tip">仅支持英文字母、数字、下划线、短横线</text>
					</view>
				</view>
				
				<view class="popup-footer">
					<u-button @click="showAddCategory = false" size="medium" plain>取消</u-button>
					<u-button type="primary" @click="submitNewCategory" size="medium">确定</u-button>
				</view>
			</view>
		</u-popup>
		
		<!-- 授权提示弹窗 -->
		<u-popup :show="showAuthPopup" @close="showAuthPopup = false" mode="center" border-radius="10">
			<view class="auth-popup">
				<view class="popup-header">
					<text class="popup-title">目录授权</text>
					<u-icon name="close" size="20" @click="showAuthPopup = false"></u-icon>
				</view>
				
				<view class="popup-content">
					<view class="auth-icon">
						<u-icon name="email-fill" size="60" color="#3B82F6"></u-icon>
					</view>
					<text class="auth-title">请选择demo文件夹</text>
					<text class="auth-desc">为了能够自动创建和管理页面文件，需要您授权访问demo文件夹。</text>
					<text class="auth-tip">点击下方按钮选择demo文件夹进行授权</text>
				</view>
				
				<view class="popup-footer">
					<u-button @click="showAuthPopup = false" size="medium" plain>稍后授权</u-button>
					<u-button type="primary" @click="selectProjectDirectory" size="medium">选择文件夹</u-button>
				</view>
			</view>
		</u-popup>

		<!-- 查看代码弹窗 -->
		<u-popup :show="showCodeViewer" @close="showCodeViewer = false" mode="center" border-radius="10">
			<view :class="['code-viewer-popup', { fullscreen: isCodeFullscreen }]">
				<view class="popup-header">
					<view class="header-left">
						<text class="popup-title">{{ currentViewPage.name }}</text>
					</view>
					<view class="header-actions">
						<view class="fullscreen-icon" @click="toggleCodeFullscreen">
							<u-icon :name="isCodeFullscreen ? 'minus-square' : 'grid'" size="16" color="#666"></u-icon>
							<text class="action-text">{{ isCodeFullscreen ? '缩小' : '放大' }}</text>
						</view>
						<view class="copy-code-icon" @click="copyCodeFromViewer">
							<u-icon name="copy" size="16" color="#DB0000"></u-icon>
							<text class="copy-text">复制</text>
						</view>
						<u-icon name="close" size="20" @click="closeCodeViewer"></u-icon>
					</view>
				</view>
				
				<view class="code-viewer-content">
					<view class="code-info-bar">
						<text class="code-file-name">{{ currentViewPage.fileName }}</text>
						<text class="code-size">{{ getCodeSize(currentViewPage.code) }}</text>
					</view>
					<scroll-view scroll-y class="code-scroll">
						<pre class="code-block">{{ currentViewPage.code }}</pre>
					</scroll-view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
	import {
		baseUrl
	} from '@/api/base.js';
	
	export default {
		data() {
			return {
				categories: [],
				pages: [],
				currentCategoryId: '',
				showUploadPopup: false,
				showCategoryPicker: false,
				showCategoryList: false, // 自定义分类列表
				showAddCategory: false, // 新增分类弹窗
				showAuthPopup: false, // 授权提示弹窗
				uploading: false,
				newCategory: {
					name: '',
					id: ''
				},
				newPage: {
					name: '',
					description: '',
					categoryId: '',
					screenshot: '',
					customFileName: '', // 自定义文件名（不含.vue）
					fileName: '', // 完整文件名（含.vue）
					code: '',
					createTime: ''
				},
				originalFileName: '', // 上传文件的原始文件名
				fileNameExists: false, // 文件名是否已存在
				codeFileSize: '', // 代码文件大小
				screenshotList: [],
				projectDirHandle: null, // 项目目录句柄
				isFileSystemSupported: false, // 是否支持 File System Access API
				showCodeViewer: false, // 显示代码查看器
				currentViewPage: {}, // 当前查看的页面
				isEditMode: false, // 是否处于编辑模式
				isCodeFullscreen: false // 代码查看器是否全屏
			};
		},
		computed: {
			currentPages() {
				if (!this.currentCategoryId) return [];
				return this.pages.filter(page => page.categoryId === this.currentCategoryId);
			},
			selectedCategoryName() {
				const category = this.categories.find(c => c.id === this.newPage.categoryId);
				return category ? category.name : '';
			}
		},
		async onLoad() {
			this.checkFileSystemSupport();
			await this.loadProjectDirHandle();
			await this.loadData();
		},
		methods: {
			// 检查浏览器是否支持 File System Access API
			checkFileSystemSupport() {
				// #ifdef H5
				if (typeof window !== 'undefined' && 'showDirectoryPicker' in window) {
					this.isFileSystemSupported = true;
					console.log('✅ 浏览器支持 File System Access API');
				} else {
					this.isFileSystemSupported = false;
					console.log('❌ 浏览器不支持 File System Access API');
				}
				// #endif
			},
			
			// 加载保存的项目目录句柄
			async loadProjectDirHandle() {
				// #ifdef H5
				if (!this.isFileSystemSupported) return;
				
				try {
					// 尝试从 IndexedDB 中恢复目录句柄
					const handle = await this.getStoredDirHandle();
					if (handle) {
						// 验证权限
						const permission = await handle.queryPermission({ mode: 'readwrite' });
						if (permission === 'granted') {
							this.projectDirHandle = handle;
							console.log('✅ 已恢复项目目录权限');
						} else {
							// 需要重新授权
							const newPermission = await handle.requestPermission({ mode: 'readwrite' });
							if (newPermission === 'granted') {
								this.projectDirHandle = handle;
								console.log('✅ 重新获取项目目录权限成功');
							}
						}
					}
				} catch (err) {
					console.log('恢复目录句柄失败:', err);
				}
				// #endif
			},
			
			// 从 IndexedDB 获取存储的目录句柄
			async getStoredDirHandle() {
				// #ifdef H5
				return new Promise((resolve) => {
					const request = indexedDB.open('PageLibraryDB', 1);
					
					request.onupgradeneeded = (event) => {
						const db = event.target.result;
						if (!db.objectStoreNames.contains('settings')) {
							db.createObjectStore('settings');
						}
					};
					
					request.onsuccess = (event) => {
						const db = event.target.result;
						const transaction = db.transaction(['settings'], 'readonly');
						const store = transaction.objectStore('settings');
						const getRequest = store.get('projectDirHandle');
						
						getRequest.onsuccess = () => {
							resolve(getRequest.result);
						};
						
						getRequest.onerror = () => {
							resolve(null);
						};
					};
					
					request.onerror = () => {
						resolve(null);
					};
				});
				// #endif
			},
			
			// 保存目录句柄到 IndexedDB
			async storeDirHandle(handle) {
				// #ifdef H5
				return new Promise((resolve) => {
					const request = indexedDB.open('PageLibraryDB', 1);
					
					request.onupgradeneeded = (event) => {
						const db = event.target.result;
						if (!db.objectStoreNames.contains('settings')) {
							db.createObjectStore('settings');
						}
					};
					
					request.onsuccess = (event) => {
						const db = event.target.result;
						const transaction = db.transaction(['settings'], 'readwrite');
						const store = transaction.objectStore('settings');
						store.put(handle, 'projectDirHandle');
						
						transaction.oncomplete = () => {
							resolve(true);
						};
						
						transaction.onerror = () => {
							resolve(false);
						};
					};
					
					request.onerror = () => {
						resolve(false);
					};
				});
				// #endif
			},
			
			// 处理添加按钮点击
			handleAddClick() {
				console.log('点击了添加按钮');
				console.log('当前 showUploadPopup:', this.showUploadPopup);
				this.showUploadPopup = true;
				console.log('设置后 showUploadPopup:', this.showUploadPopup);
			},
			
			// 处理编辑按钮点击
			handleEditClick() {
				if (!this.projectDirHandle) {
					this.showAuthPopup = true;
					return;
				}
				this.toggleEditMode();
			},
			
			// 处理新增分类按钮点击
			handleAddCategoryClick() {
				if (!this.projectDirHandle) {
					this.showAuthPopup = true;
					return;
				}
				this.showAddCategory = true;
			},
			
			// 处理添加页面按钮点击
			handleAddPageClick() {
				if (!this.projectDirHandle) {
					this.showAuthPopup = true;
					return;
				}
				this.handleAddClick();
			},
			
			// 切换编辑模式
			toggleEditMode() {
				this.isEditMode = !this.isEditMode;
				console.log('编辑模式:', this.isEditMode ? '开启' : '关闭');
				
				const tip = this.isEditMode ? '现在可以删除页面和分类' : '已退出编辑模式';
				uni.showToast({
					title: tip,
					icon: 'none',
					duration: 1500
				});
			},
			
		// 处理授权按钮点击
		handleAuthClick() {
			if (this.projectDirHandle) {
				// 已授权，显示信息
				uni.showModal({
					title: '目录已授权',
					content: `当前授权目录：${this.projectDirHandle.name}\n\n提交页面时会自动在本地创建文件。\n\n是否重新选择目录？`,
					confirmText: '重新选择',
					cancelText: '保持当前',
					success: async (res) => {
						if (res.confirm) {
							await this.selectProjectDirectory();
						}
					}
				});
			} else {
				// 未授权，显示授权提示弹窗
				this.showAuthPopup = true;
			}
		},
			
			// 选择项目目录
			async selectProjectDirectory() {
				// #ifdef H5
				if (!this.isFileSystemSupported) {
					uni.showModal({
						title: '浏览器不支持',
						content: '当前浏览器不支持 File System Access API，请使用 Chrome 86+ 或 Edge 86+ 浏览器',
						showCancel: false
					});
					return;
				}
				
			try {
				// 请求用户选择目录
				const dirHandle = await window.showDirectoryPicker({
					mode: 'readwrite',
					startIn: 'documents'
				});
				
				this.projectDirHandle = dirHandle;
				
				// 保存到 IndexedDB
				await this.storeDirHandle(dirHandle);
				
				// 关闭授权弹窗
				this.showAuthPopup = false;
				
				// 加载数据
				await this.loadData();
				
				uni.showToast({
					title: '授权成功，数据已加载',
					icon: 'success',
					duration: 2000
				});
				
			} catch (err) {
				if (err.name === 'AbortError') {
					console.log('用户取消选择目录');
				} else {
					console.error('选择目录失败:', err);
					uni.showToast({
						title: '选择目录失败',
						icon: 'none'
					});
				}
			}
				// #endif
			},
			
			// 加载数据（从本地 JSON 文件）
			async loadData() {
				// #ifdef H5
				if (!this.isFileSystemSupported || !this.projectDirHandle) {
					console.log('⚠️ 未授权或不支持文件系统，跳过数据加载');
					this.categories = [];
					this.pages = [];
					return;
				}
				
				try {
					// 获取 page-library/data.json 文件
					const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
						create: true 
					});
					
					const dataFileHandle = await pageLibraryDir.getFileHandle('data.json', { 
						create: true 
					});
					
					// 读取文件内容
					const file = await dataFileHandle.getFile();
					const content = await file.text();
					
					if (content.trim()) {
						const data = JSON.parse(content);
						this.categories = data.categories || [];
						this.pages = data.pages || [];
					} else {
						// 文件为空，初始化数据
						this.categories = [];
						this.pages = [];
						await this.saveData(); // 写入初始结构
					}
					
					// 默认选中第一个分类
					if (this.categories.length > 0) {
						this.currentCategoryId = this.categories[0].id;
					}
					
					console.log('✅ 数据加载完成:', {
						categories: this.categories.length,
						pages: this.pages.length
					});
					
				} catch (err) {
					console.error('❌ 加载数据失败:', err);
					this.categories = [];
					this.pages = [];
				}
				// #endif
				
				// #ifndef H5
				// 非 H5 环境，使用 localStorage 降级
				const dataStr = uni.getStorageSync('page-library-data');
				if (dataStr) {
					const data = JSON.parse(dataStr);
					this.categories = data.categories || [];
					this.pages = data.pages || [];
				} else {
					this.categories = [];
					this.pages = [];
				}
				
				if (this.categories.length > 0) {
					this.currentCategoryId = this.categories[0].id;
				}
				// #endif
			},
			
			// 保存数据（写入本地 JSON 文件）
			async saveData() {
				const data = {
					categories: this.categories,
					pages: this.pages
				};
				
				// #ifdef H5
				if (!this.isFileSystemSupported || !this.projectDirHandle) {
					console.log('⚠️ 未授权或不支持文件系统，跳过数据保存');
					return false;
				}
				
				try {
					// 获取 page-library/data.json 文件
					const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
						create: true 
					});
					
					const dataFileHandle = await pageLibraryDir.getFileHandle('data.json', { 
						create: true 
					});
					
					// 写入数据（格式化 JSON）
					const writable = await dataFileHandle.createWritable();
					await writable.write(JSON.stringify(data, null, 2));
					await writable.close();
					
					console.log('✅ 数据已保存到 data.json');
					return true;
					
				} catch (err) {
					console.error('❌ 保存数据失败:', err);
					return false;
				}
				// #endif
				
				// #ifndef H5
				// 非 H5 环境，使用 localStorage 降级
				uni.setStorageSync('page-library-data', JSON.stringify(data));
				return true;
				// #endif
			},
			
			// 选择分类
			selectCategory(categoryId) {
				this.currentCategoryId = categoryId;
				console.log('切换到分类:', categoryId);
			},
			
			// 确认删除分类
			confirmDeleteCategory(category) {
				// 检查该分类下是否有页面
				const pageCount = this.getCategoryPageCount(category.id);
				
				// 如果分类下有页面，不允许删除
				if (pageCount > 0) {
					uni.showModal({
						title: '无法删除',
						content: `分类"${category.name}"下还有 ${pageCount} 个页面。\n\n请先删除或移动这些页面，再删除分类。`,
						showCancel: false,
						confirmText: '我知道了'
					});
					return;
				}
				
				// 空分类才能删除
				uni.showModal({
					title: '确认删除',
					content: `确定要删除分类"${category.name}"吗？`,
					confirmText: '删除',
					confirmColor: '#ff4d4f',
					success: (res) => {
						if (res.confirm) {
							this.deleteCategory(category);
						}
					}
				});
			},
			
			// 删除分类
			deleteCategory(category) {
				// 找到分类的索引
				const index = this.categories.findIndex(c => c.id === category.id);
				if (index === -1) {
					uni.showToast({
						title: '分类不存在',
						icon: 'none'
					});
					return;
				}
				
				// 从数组中删除
				this.categories.splice(index, 1);
				
				// 如果删除的是当前选中的分类，切换到第一个分类
				if (this.currentCategoryId === category.id) {
					if (this.categories.length > 0) {
						this.currentCategoryId = this.categories[0].id;
					} else {
						this.currentCategoryId = '';
					}
				}
				
				// 保存数据
				this.saveData();
				
				// 强制更新视图
				this.$forceUpdate();
				
				uni.showToast({
					title: '分类已删除',
					icon: 'success'
				});
				
				console.log('分类已删除:', category.name);
				console.log('剩余分类数量:', this.categories.length);
			},
			
			// 获取分类下的页面数量
			getCategoryPageCount(categoryId) {
				return this.pages.filter(page => page.categoryId === categoryId).length;
			},
			
			// 格式化时间
			formatTime(timestamp) {
				if (!timestamp) return '';
				const date = new Date(timestamp);
				return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
			},
			
			// 上传效果图后
			afterReadScreenshot(event) {
				const file = event.file;
				uni.showLoading({ title: '上传中...' });
				
				uni.uploadFile({
					url: baseUrl + '/api/upload/uploadFile',
					filePath: file.url,
					name: 'file',
					success: (res) => {
						const data = JSON.parse(res.data);
						if (data.code === 200) {
							this.newPage.screenshot = data.data;
							this.screenshotList = [{
								url: data.data,
								status: 'success'
							}];
							uni.showToast({ title: '上传成功', icon: 'success' });
						} else {
							uni.showToast({ title: '上传失败', icon: 'none' });
						}
					},
					fail: () => {
						uni.showToast({ title: '上传失败', icon: 'none' });
					},
					complete: () => {
						uni.hideLoading();
					}
				});
			},
			
			// 删除效果图
			deleteScreenshot() {
				this.newPage.screenshot = '';
				this.screenshotList = [];
			},
			
			// 选择代码文件
			chooseCodeFile() {
				// #ifdef H5
				const input = document.createElement('input');
				input.type = 'file';
				input.accept = '.vue';
				input.onchange = (e) => {
					const file = e.target.files[0];
					if (file) {
						// 保存原始文件名
						this.originalFileName = file.name;
						
						// 计算文件大小
						const size = file.size;
						if (size < 1024) {
							this.codeFileSize = size + 'B';
						} else if (size < 1024 * 1024) {
							this.codeFileSize = (size / 1024).toFixed(2) + 'KB';
						} else {
							this.codeFileSize = (size / 1024 / 1024).toFixed(2) + 'MB';
						}
						
						// 如果用户还没输入自定义文件名，自动从原文件名提取
						if (!this.newPage.customFileName) {
							const nameWithoutExt = file.name.replace('.vue', '');
							// 转换为合法的文件名格式
							const cleanName = nameWithoutExt.toLowerCase()
								.replace(/[^a-z0-9_-]/g, '-')
								.replace(/-+/g, '-')
								.replace(/^-|-$/g, '');
							this.newPage.customFileName = cleanName;
							
							// 检查是否重名
							this.checkFileNameExists();
						}
						
						// 读取文件内容
						const reader = new FileReader();
						reader.onload = (event) => {
							this.newPage.code = event.target.result;
							console.log('文件读取成功，大小:', this.codeFileSize);
						};
						reader.readAsText(file);
					}
				};
				input.click();
				// #endif
				
				// #ifndef H5
				uni.showToast({
					title: '请在H5环境下使用此功能',
					icon: 'none'
				});
				// #endif
			},
			
			// 验证文件名格式
			validateFileName(e) {
				// 只允许英文字母、数字、下划线、短横线
				let value = e.detail.value;
				value = value.replace(/[^a-zA-Z0-9_-]/g, '');
				this.newPage.customFileName = value.toLowerCase();
				
				// 实时检查是否重名
				this.checkFileNameExists();
			},
			
			// 检查文件名是否已存在（仅提示，不阻止）
			async checkFileNameExists() {
				if (!this.newPage.customFileName || !this.newPage.categoryId) {
					this.fileNameExists = false;
					return false;
				}
				
				const fullFileName = this.newPage.customFileName + '.vue';
				
				// 1. 检查数据库中是否有同名文件
				const existsInData = this.pages.some(page => 
					page.categoryId === this.newPage.categoryId && 
					page.fileName === fullFileName
				);
				
				// 2. 检查本地文件系统中是否有同名文件
				const existsInLocal = await this.checkLocalFileExists(this.newPage.categoryId, fullFileName);
				
				// 只要有一个地方存在就算重复
				const exists = existsInData || existsInLocal;
				
				this.fileNameExists = exists;
				
				if (exists) {
					console.log('⚠️ 文件名已存在，提交时将自动添加索引:', fullFileName);
				} else {
					console.log('✅ 文件名可用:', fullFileName);
				}
				
				return exists;
			},
			
			// 自动生成不重复的文件名（添加索引）
			async generateUniqueFileName(baseName, categoryId) {
				let finalName = baseName;
				let counter = 1;
				
				// 先检查基础名称是否可用
				const baseFileName = baseName + '.vue';
				const baseExistsInData = this.pages.some(page => 
					page.categoryId === categoryId && 
					page.fileName === baseFileName
				);
				const baseExistsInLocal = await this.checkLocalFileExists(categoryId, baseFileName);
				
				// 如果基础名称不存在，直接使用
				if (!baseExistsInData && !baseExistsInLocal) {
					console.log('✅ 文件名可用:', baseName);
					return baseName;
				}
				
				// 否则，添加索引 _1, _2, _3...
				while (counter <= 200) {
					const testName = `${baseName}_${counter}`;
					const testFileName = testName + '.vue';
					
					// 检查数据库
					const existsInData = this.pages.some(page => 
						page.categoryId === categoryId && 
						page.fileName === testFileName
					);
					
					// 检查本地文件
					const existsInLocal = await this.checkLocalFileExists(categoryId, testFileName);
					
					// 如果两个地方都不存在，就是可用的名称
					if (!existsInData && !existsInLocal) {
						console.log(`💡 文件名已存在，自动添加索引：${baseName} → ${testName}`);
						finalName = testName;
						break;
					}
					counter++;
				}
				
				if (counter > 200) {
					console.error('⚠️ 已有200个同名文件，请使用不同的基础名称');
					throw new Error('文件名冲突次数过多');
				}
				
				return finalName;
			},
			
			// 打开分类选择器
			openCategorySelector() {
				console.log('=== 打开分类选择器 ===');
				console.log('左侧分类数量:', this.categories.length);
				console.log('分类列表:', this.categories.map(c => c.name));
				
				this.showCategoryList = true;
				this.$forceUpdate(); // 强制更新视图
			},
			
			// 从列表中选择分类
			selectCategoryFromList(category) {
				console.log('选择分类:', category.name);
				this.newPage.categoryId = category.id;
				this.showCategoryList = false;
				
				// 切换分类后重新检查文件名
				if (this.newPage.customFileName) {
					this.checkFileNameExists();
				}
			},
			
			// 调试：检查分类列表状态
			checkCategoryListStatus() {
				console.log('=== 分类列表状态 ===');
				console.log('showCategoryList:', this.showCategoryList);
				console.log('分类数量:', this.categories.length);
				console.log('分类列表:', this.categories);
				console.log('当前选中分类:', this.currentCategoryId);
			},
			
			// 调试：打印所有分类（用于测试）
			debugCategories() {
				console.log('=== 完整分类信息 ===');
				console.log('总数:', this.categories.length);
				this.categories.forEach((cat, index) => {
					console.log(`${index + 1}. ${cat.name} (ID: ${cat.id})`);
				});
			},
			
			// 显示新增分类对话框
			showAddCategoryDialog() {
				console.log('=== 点击新增分类 ===');
				console.log('当前分类数量:', this.categories.length);
				
				this.showCategoryList = false;
				this.newCategory = {
					name: '',
					id: ''
				};
				
				// 延迟打开，确保分类列表弹窗已关闭
				this.$nextTick(() => {
					this.showAddCategory = true;
				});
			},
			
			// 验证英文名称格式
			validateEnglishName(e) {
				// 只允许英文字母、数字、下划线、短横线
				let value = e.detail.value;
				value = value.replace(/[^a-zA-Z0-9_-]/g, '');
				this.newCategory.id = value.toLowerCase(); // 转为小写
			},
			
			// 提交新分类
			async submitNewCategory() {
				// 验证分类名称
				if (!this.newCategory.name.trim()) {
					uni.showToast({ 
						title: '请输入分类名称', 
						icon: 'none' 
					});
					return;
				}
				
				// 验证英文名称
				if (!this.newCategory.id.trim()) {
					uni.showToast({ 
						title: '请输入英文名称', 
						icon: 'none' 
					});
					return;
				}
				
				// 验证英文名称格式
				const englishNamePattern = /^[a-z0-9_-]+$/;
				if (!englishNamePattern.test(this.newCategory.id.trim())) {
					uni.showToast({ 
						title: '英文名称格式不正确', 
						icon: 'none' 
					});
					return;
				}
				
				// 检查分类名称是否已存在
				const existingByName = this.categories.find(c => c.name === this.newCategory.name.trim());
				if (existingByName) {
					uni.showToast({ 
						title: '该分类名称已存在', 
						icon: 'none' 
					});
					return;
				}
				
				// 检查英文名称（ID）是否已存在
				const existingById = this.categories.find(c => c.id === this.newCategory.id.trim());
				if (existingById) {
					uni.showToast({ 
						title: '该英文名称已被使用', 
						icon: 'none' 
					});
					return;
				}
				
				// 使用英文名称作为分类ID
				const categoryId = this.newCategory.id.trim();
				
				// 创建新分类
				const newCategoryData = {
					id: categoryId,
					name: this.newCategory.name.trim()
				};
				
				// 添加到分类列表
				this.categories.push(newCategoryData);
				
				// 保存数据
				this.saveData();
				
				console.log('=== 分类创建完成 ===');
				console.log('新分类:', newCategoryData);
				console.log('总分类数量:', this.categories.length);
				console.log('所有分类:', this.categories.map(c => c.name));
				
				// 强制触发视图更新
				this.$forceUpdate();
				
				// 如果支持文件系统，创建对应文件夹
				await this.createCategoryFolder(categoryId);
				
				// 自动选中新创建的分类
				this.newPage.categoryId = categoryId;
				
				// 切换到新分类（在左侧分类列表）
				this.currentCategoryId = categoryId;
				
				// 关闭弹窗
				this.showAddCategory = false;
				
				uni.showToast({ 
					title: '分类创建成功', 
					icon: 'success' 
				});
				
				console.log('新分类已创建并选中:', newCategoryData);
				console.log('当前选中分类ID:', this.currentCategoryId);
			},
			
			// 创建分类文件夹（本地文件系统）
			async createCategoryFolder(categoryId) {
				// #ifdef H5
				if (!this.isFileSystemSupported || !this.projectDirHandle) {
					return false;
				}
				
				try {
					// 获取/创建 page-library 目录
					const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
						create: true 
					});
					
					// 获取/创建 pages 目录
					const pagesDir = await pageLibraryDir.getDirectoryHandle('pages', { 
						create: true 
					});
					
					// 创建新分类目录
					await pagesDir.getDirectoryHandle(categoryId, { 
						create: true 
					});
					
					console.log(`✅ 分类文件夹创建成功: page-library/pages/${categoryId}`);
					return true;
					
				} catch (err) {
					console.error('创建分类文件夹失败:', err);
					return false;
				}
				// #endif
				
				// #ifndef H5
				return false;
				// #endif
			},
			
			// 确认选择分类（u-picker 回调，保留兼容）
			onCategoryConfirm(e) {
				console.log('u-picker 选择分类:', e);
				const index = e.index !== undefined ? e.index : e;
				if (this.categories[index]) {
					this.newPage.categoryId = this.categories[index].id;
					console.log('已选择分类:', this.categories[index].name);
				}
				this.showCategoryPicker = false;
			},
			
			// 提交新页面
			async submitNewPage() {
				// 验证页面名称
				if (!this.newPage.name.trim()) {
					uni.showToast({ title: '请输入页面名称', icon: 'none' });
					return;
				}
				
				// 验证分类
				if (!this.newPage.categoryId) {
					uni.showToast({ title: '请选择分类', icon: 'none' });
					return;
				}
				
				// 验证文件名
				if (!this.newPage.customFileName.trim()) {
					uni.showToast({ title: '请输入文件名称', icon: 'none' });
					return;
				}
				
				// 验证文件名格式
				const fileNamePattern = /^[a-z0-9_-]+$/;
				if (!fileNamePattern.test(this.newPage.customFileName.trim())) {
					uni.showToast({ title: '文件名格式不正确', icon: 'none' });
					return;
				}
				
				// 自动处理文件名冲突（添加索引）
				let finalFileName = this.newPage.customFileName.trim();
				
				// 如果文件名已存在，自动生成不重复的名称
				try {
					finalFileName = await this.generateUniqueFileName(
						this.newPage.customFileName.trim(), 
						this.newPage.categoryId
					);
					
					if (finalFileName !== this.newPage.customFileName.trim()) {
						console.log(`📝 文件名自动调整：${this.newPage.customFileName} → ${finalFileName}`);
					}
				} catch (err) {
					uni.showToast({ 
						title: err.message || '文件名处理失败', 
						icon: 'none' 
					});
					this.uploading = false;
					return;
				}
				
				// 验证效果图
				if (!this.newPage.screenshot) {
					uni.showToast({ title: '请上传效果图', icon: 'none' });
					return;
				}
				
				// 验证代码文件
				if (!this.newPage.code) {
					uni.showToast({ title: '请选择页面代码文件', icon: 'none' });
					return;
				}
				
				this.uploading = true;
				
				// 生成唯一ID
				const pageId = 'page_' + Date.now();
				
				// 生成完整文件名（已经是不重复的）
				const fullFileName = finalFileName + '.vue';
				
			// 添加到列表（不保存 code 到 JSON）
			const newPageData = {
				id: pageId,
				name: this.newPage.name,
				description: this.newPage.description,
				categoryId: this.newPage.categoryId,
				screenshot: this.newPage.screenshot,
				fileName: fullFileName,
				createTime: Date.now()
			};
				
			console.log('=== 准备创建页面 ===');
			console.log('页面名称:', newPageData.name);
			console.log('文件名称:', newPageData.fileName);
			console.log('所属分类:', newPageData.categoryId);
			
			// 尝试在本地创建文件（传入代码）
			const fileCreated = await this.createLocalFile(newPageData, this.newPage.code);
			
			this.pages.push(newPageData);
			this.saveData();
				
				// 重置表单
				this.resetForm();
				this.showUploadPopup = false;
				this.uploading = false;
				
				// 提示成功（显示最终的文件名）
				const successMsg = finalFileName !== this.newPage.customFileName.trim() 
					? `页面已添加！\n文件名自动调整为：${finalFileName}.vue` 
					: '页面添加成功！';
				
				if (fileCreated) {
					uni.showModal({
						title: '提交成功',
						content: `✅ ${successMsg}\n✅ 本地文件已创建：\npage-library/pages/${newPageData.categoryId}/${newPageData.fileName}`,
						showCancel: false,
						confirmText: '知道了'
					});
				} else {
					uni.showToast({ 
						title: successMsg, 
						icon: 'success',
						duration: 2000
					});
				}
				
				// 切换到对应分类
				this.currentCategoryId = newPageData.categoryId;
			},
			
			// 检查本地文件是否已存在
			async checkLocalFileExists(categoryId, fileName) {
				// #ifdef H5
				if (!this.isFileSystemSupported || !this.projectDirHandle) {
					return false;
				}
				
				try {
					const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
						create: false 
					});
					const pagesDir = await pageLibraryDir.getDirectoryHandle('pages', { 
						create: false 
					});
					const categoryDir = await pagesDir.getDirectoryHandle(categoryId, { 
						create: false 
					});
					
					// 尝试获取文件（不创建）
					const fileHandle = await categoryDir.getFileHandle(fileName, { 
						create: false 
					});
					
					// 如果没有报错，说明文件存在
					return true;
					
				} catch (err) {
					// 文件或目录不存在
					return false;
				}
				// #endif
				
				// #ifndef H5
				return false;
				// #endif
			},
			
		// 在本地创建文件
		async createLocalFile(pageData, code) {
			// #ifdef H5
			if (!this.isFileSystemSupported) {
				console.log('浏览器不支持 File System Access API，跳过本地文件创建');
				return false;
			}
			
			// 检查是否已授权目录
			if (!this.projectDirHandle) {
				const result = await new Promise((resolve) => {
					uni.showModal({
						title: '需要授权项目目录',
						content: '要在本地创建文件，需要授权访问项目目录。\n\n是否现在授权？',
						success: (res) => {
							resolve(res.confirm);
						}
					});
				});
				
				if (result) {
					await this.selectProjectDirectory();
					if (!this.projectDirHandle) {
						return false;
					}
				} else {
					return false;
				}
			}
			
			try {
				// 1. 获取/创建 page-library 目录
				const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
					create: true 
				});
				
				// 2. 获取/创建 pages 目录
				const pagesDir = await pageLibraryDir.getDirectoryHandle('pages', { 
					create: true 
				});
				
				// 3. 获取/创建分类目录
				const categoryDir = await pagesDir.getDirectoryHandle(pageData.categoryId, { 
					create: true 
				});
				
				// 4. 直接创建文件（因为文件名已经是唯一的，不需要再确认）
				const fileHandle = await categoryDir.getFileHandle(pageData.fileName, { 
					create: true 
				});
				
				// 5. 写入代码
				const writable = await fileHandle.createWritable();
				await writable.write(code);
				await writable.close();
				
				console.log(`✅ 本地文件创建成功: page-library/pages/${pageData.categoryId}/${pageData.fileName}`);
				return true;
				
			} catch (err) {
				console.error('创建本地文件失败:', err);
				
				if (err.name === 'NotAllowedError') {
					uni.showModal({
						title: '权限被拒绝',
						content: '无法创建文件，可能权限已过期。\n\n是否重新授权？',
						success: async (res) => {
							if (res.confirm) {
								this.projectDirHandle = null;
								await this.selectProjectDirectory();
							}
						}
					});
				} else {
					uni.showToast({
						title: '创建文件失败：' + err.message,
						icon: 'none',
						duration: 3000
					});
				}
				
				return false;
			}
			// #endif
			
			// #ifndef H5
			return false;
			// #endif
		},
			
			// 重置表单
			resetForm() {
				this.newPage = {
					name: '',
					description: '',
					categoryId: '',
					screenshot: '',
					customFileName: '',
					fileName: '',
					code: '',
					createTime: ''
				};
				this.screenshotList = [];
				this.showCategoryList = false;
				this.originalFileName = '';
				this.fileNameExists = false;
				this.codeFileSize = '';
			},
			
		// 查看代码（从本地文件读取）
		async viewCode(page) {
			console.log('查看代码:', page.name);
			
			// 从本地文件读取代码
			const code = await this.readLocalFileCode(page);
			
			if (!code) {
				uni.showToast({
					title: '无法读取文件代码',
					icon: 'none'
				});
				return;
			}
			
			this.currentViewPage = {
				...page,
				code: code
			};
			this.showCodeViewer = true;
			this.isCodeFullscreen = false;
		},
		
		// 从本地文件读取代码
		async readLocalFileCode(page) {
			// #ifdef H5
			if (!this.isFileSystemSupported || !this.projectDirHandle) {
				console.log('⚠️ 未授权或不支持文件系统');
				return null;
			}
			
			try {
				// 构建文件路径
				const pageLibraryDir = await this.projectDirHandle.getDirectoryHandle('page-library', { 
					create: false 
				});
				const pagesDir = await pageLibraryDir.getDirectoryHandle('pages', { 
					create: false 
				});
				const categoryDir = await pagesDir.getDirectoryHandle(page.categoryId, { 
					create: false 
				});
				const fileHandle = await categoryDir.getFileHandle(page.fileName, { 
					create: false 
				});
				
				// 读取文件内容
				const file = await fileHandle.getFile();
				const code = await file.text();
				
				console.log('✅ 成功读取文件代码:', page.fileName);
				return code;
				
			} catch (err) {
				console.error('❌ 读取文件代码失败:', err);
				return null;
			}
			// #endif
			
			// #ifndef H5
			return null;
			// #endif
		},
			
			// 关闭代码查看器
			closeCodeViewer() {
				this.showCodeViewer = false;
				this.isCodeFullscreen = false;
			},
			
			// 切换代码查看器全屏
			toggleCodeFullscreen() {
				this.isCodeFullscreen = !this.isCodeFullscreen;
				console.log('代码查看器全屏:', this.isCodeFullscreen);
			},
			
		// 从代码查看器复制代码
		async copyCodeFromViewer() {
			await this.copyCode(this.currentViewPage);
		},
			
			// 获取代码大小
			getCodeSize(code) {
				if (!code) return '0B';
				const size = new Blob([code]).size;
				if (size < 1024) {
					return size + 'B';
				} else if (size < 1024 * 1024) {
					return (size / 1024).toFixed(2) + 'KB';
				} else {
					return (size / 1024 / 1024).toFixed(2) + 'MB';
				}
			},
			
		// 复制代码（从本地文件读取）
		async copyCode(page) {
			// 如果 page.code 已经存在（从查看器打开的），直接复制
			let code = page.code;
			
			// 如果没有 code，从本地文件读取
			if (!code) {
				code = await this.readLocalFileCode(page);
				if (!code) {
					uni.showToast({ title: '无法读取文件代码', icon: 'none' });
					return;
				}
			}
			
			// #ifdef H5
			if (navigator.clipboard) {
				navigator.clipboard.writeText(code).then(() => {
					uni.showToast({ title: '代码已复制', icon: 'success' });
				}).catch(() => {
					uni.showToast({ title: '复制失败', icon: 'none' });
				});
			} else {
				// 降级方案
				const textarea = document.createElement('textarea');
				textarea.value = code;
				document.body.appendChild(textarea);
				textarea.select();
				document.execCommand('copy');
				document.body.removeChild(textarea);
				uni.showToast({ title: '代码已复制', icon: 'success' });
			}
			// #endif
			
			// #ifndef H5
			uni.setClipboardData({
				data: code,
				success: () => {
					uni.showToast({ title: '代码已复制', icon: 'success' });
				}
			});
			// #endif
		},
			
			// 复制路径（相对路径）
			copyPath(page) {
				// 构建相对路径（fileName 已包含 .vue 后缀）
				const relativePath = `ReferenceTemplate/page-library/pages/${page.categoryId}/${page.fileName}`;
				
				console.log('复制相对路径:', relativePath);
				
				// #ifdef H5
				if (navigator.clipboard) {
					navigator.clipboard.writeText(relativePath).then(() => {
						uni.showToast({ 
							title: '相对路径已复制', 
							icon: 'success',
							duration: 2000
						});
					});
				} else {
					const textarea = document.createElement('textarea');
					textarea.value = relativePath;
					document.body.appendChild(textarea);
					textarea.select();
					document.execCommand('copy');
					document.body.removeChild(textarea);
					uni.showToast({ 
						title: '相对路径已复制', 
						icon: 'success',
						duration: 2000
					});
				}
				// #endif
				
				// #ifndef H5
				uni.setClipboardData({
					data: relativePath,
					success: () => {
						uni.showToast({ 
							title: '相对路径已复制', 
							icon: 'success',
							duration: 2000
						});
					}
				});
				// #endif
			},
			
			// 删除页面
			async deletePage(page, index) {
				uni.showModal({
					title: '确认删除',
					content: `确定要删除"${page.name}"吗？\n\n注意：这将同时删除本地文件系统中的对应文件。`,
					success: async (res) => {
						if (res.confirm) {
							try {
								// 删除本地文件
								await this.deleteLocalFile(page);
								
								// 从数据中删除
								const pageIndex = this.pages.findIndex(p => p.id === page.id);
								if (pageIndex > -1) {
									this.pages.splice(pageIndex, 1);
									this.saveData();
									uni.showToast({ title: '删除成功', icon: 'success' });
									console.log('页面已删除:', page.name);
								}
							} catch (error) {
								console.error('删除文件失败:', error);
								uni.showToast({ 
									title: '删除文件失败，但页面数据已删除', 
									icon: 'none',
									duration: 2000
								});
							}
						}
					}
				});
			},
			
			// 删除本地文件
			async deleteLocalFile(page) {
				// #ifdef H5
				if (this.isFileSystemSupported && this.projectDirHandle) {
					try {
						// 构建文件路径：page-library/pages/{categoryId}/{fileName}
						const filePath = `page-library/pages/${page.categoryId}/${page.fileName}`;
						
						// 获取目录句柄
						const dirHandle = await this.projectDirHandle.getDirectoryHandle('page-library');
						const pagesDir = await dirHandle.getDirectoryHandle('pages');
						const categoryDir = await pagesDir.getDirectoryHandle(page.categoryId);
						
						// 删除文件（fileName 已包含 .vue 后缀）
						await categoryDir.removeEntry(page.fileName);
						
						console.log('本地文件已删除:', filePath);
					} catch (error) {
						console.error('删除本地文件失败:', error);
						// 不抛出错误，允许继续删除数据
					}
				}
				// #endif
			}
		}
	};
</script>

<style lang="scss" scoped>
	.page-library {
		height: 100vh;
		background-color: #F7F7F7;
		overflow: hidden;
	}

	/* 导航栏右侧按钮 */
	.nav-right-btns {
		display: flex;
		align-items: center;
		gap: 20rpx;
	}
	.logo{
		
	}

	.auth-status {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 12rpx 20rpx;
		border-radius: 8rpx;
		background-color: #3B82F6;
		transition: all 0.2s;

		&:active {
			transform: scale(0.95);
		}

		.status-text {
			font-size: 24rpx;
			color: #FFFFFF;
			font-weight: 600;
		}
	}

	.edit-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 12rpx 20rpx;
		border-radius: 8rpx;
		background-color: #3B82F6;
		transition: all 0.2s;

		&:active {
			transform: scale(0.95);
		}

		&.disabled {
			background-color: #CCCCCC;
			cursor: not-allowed;
			
			&:active {
				transform: none;
			}
		}

		.edit-text {
			font-size: 24rpx;
			color: #FFFFFF;
			font-weight: 600;
		}
	}

	.add-category-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 12rpx 20rpx;
		border-radius: 8rpx;
		background-color: #3B82F6;
		transition: all 0.2s;

		&:active {
			transform: scale(0.95);
		}

		.add-category-text {
			font-size: 24rpx;
			color: #FFFFFF;
			font-weight: 600;
		}
	}

	.add-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 12rpx 20rpx;
		border-radius: 8rpx;
		background-color: #3B82F6;
		transition: all 0.2s;

		&:active {
			transform: scale(0.95);
		}

		&.disabled {
			background-color: #CCCCCC;
			cursor: not-allowed;
			
			&:active {
				transform: none;
			}
		}

		.add-text {
			font-size: 24rpx;
			color: #FFFFFF;
			font-weight: 600;
		}
	}

	.content-wrapper {
		flex: 1;
		display: flex;
		overflow: hidden;
		height: 100vh;
	}

	/* 左侧分类 */
	.category-sidebar {
		width: 280rpx;
		background: linear-gradient(to bottom, #ffffff 0%, #f8f9fa 100%);
		border-right: 2rpx solid #E8E8E8;
		box-shadow: 2rpx 0 12rpx rgba(0, 0, 0, 0.04);
		display: flex;
		flex-direction: column;
	}


	.category-scroll {
		flex: 1;
		height: 0;
	}

	.category-item {
		position: relative;
		min-height: 100rpx;
		margin: 10rpx 16rpx;
		border-radius: 12rpx;
		overflow: hidden;
		transition: all 0.2s;

		.category-content {
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			padding: 28rpx 16rpx;
			min-height: 100rpx;
			// background-color: #FFFFFF;
			transition: all 0.2s;
		}

		.category-name {
			font-size: 26rpx;
			color: #666666;
			text-align: center;
			line-height: 1.5;
			word-break: break-all;
			font-weight: 500;
			transition: all 0.2s;
			
			.count-text {
				font-size: 22rpx;
				color: #999999;
				font-weight: 400;
				margin-left: 4rpx;
			}
		}

		.delete-category-btn {
			position: absolute;
			top: 8rpx;
			left: 8rpx;
			width: 36rpx;
			height: 36rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			background-color: rgba(255, 255, 255, 0.98);
			border-radius: 50%;
			z-index: 2;
			box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);

			&:active {
				background-color: #FFE5E5;
				transform: scale(0.9);
			}
		}

		&:hover {
			transform: translateX(4rpx);
		}

		&.active {
			.category-content {
				background-color: #FFFFFF;
			}

			.category-name {
				color: #3B82F6;
				font-weight: 600;
				
				.count-text {
					color: #3B82F6;
				}
			}
		}
	}

	/* 右侧页面列表 */
	.page-list-wrapper {
		flex: 1;
		overflow: hidden;
	}

	.page-scroll {
		height: 100%;
	}

	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		min-height: 100%;
		padding: 200rpx 30rpx;

		.empty-text {
			font-size: 28rpx;
			color: #999999;
			margin-top: 20rpx;
		}

		.add-btn-wrapper {
			margin-top: 40rpx;
		}
	}

	.page-grid {
		display: flex;
		flex-wrap: wrap;
		gap: 30rpx;
		padding: 30rpx;
		box-sizing: border-box;
	}

	.page-card {
		width: 375px;
		background-color: #FFFFFF;
		border-radius: 16rpx;
		overflow: hidden;
		position: relative;
		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
		transition: all 0.2s;

		&:hover {
			transform: translateY(-4rpx);
			box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.12);
		}
	}

	.screenshot-wrapper {
		width: 375px;
		height: 600px;
		background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
		overflow: hidden;
		position: relative;
		
		&::after {
			content: '';
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			background: rgba(0, 0, 0, 0.02);
			pointer-events: none;
		}

		.screenshot-image {
			width: 100%;
			height: 100%;
			object-fit: cover;
			background-color: #fff;
		}
	}

	.page-name-section {
		padding: 24rpx 20rpx;
		border-bottom: 1rpx solid #F0F0F0;
		background-color: #FFFFFF;

		.page-name {
			font-size: 32rpx;
			color: #333333;
			font-weight: 600;
			display: block;
			margin-bottom: 8rpx;
			line-height: 1.4;
		}

		.page-file-name {
			font-size: 24rpx;
			color: #999999;
			display: block;
			font-family: 'Monaco', 'Courier New', monospace;
		}
	}

	.action-buttons {
		display: flex;
		gap: 16rpx;
		padding: 20rpx;

		.action-btn {
			flex: 1;
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 8rpx;
			height: 72rpx;
			border-radius: 10rpx;
			font-size: 26rpx;
			color: #FFFFFF;
			font-weight: 500;
			transition: transform 0.2s;
			
			&:active {
				transform: scale(0.95);
			}

			&.view-code-btn {
				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
				box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.4);
			}

			&.copy-path-btn {
				background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
				box-shadow: 0 4rpx 12rpx rgba(240, 147, 251, 0.4);
			}
		}
	}

	.delete-btn {
		position: absolute;
		top: 16rpx;
		right: 16rpx;
		width: 60rpx;
		height: 60rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		background-color: rgba(255, 255, 255, 0.98);
		border-radius: 50%;
		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
		transition: all 0.2s;
		z-index: 10;
		
		&:active {
			transform: scale(0.9);
			box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
		}
	}

	/* 授权提示弹窗 */
	.auth-popup {
		width: 600rpx;
		background-color: #FFFFFF;
		border-radius: 20rpx;
		overflow: hidden;
	}

	.auth-icon {
		display: flex;
		justify-content: center;
		margin-bottom: 30rpx;
	}

	.auth-title {
		font-size: 32rpx;
		font-weight: 600;
		color: #333333;
		text-align: center;
		margin-bottom: 20rpx;
		display: block;
	}

	.auth-desc {
		font-size: 26rpx;
		color: #666666;
		text-align: center;
		line-height: 1.6;
		margin-bottom: 20rpx;
		display: block;
	}

	.auth-tip {
		font-size: 24rpx;
		color: #999999;
		text-align: center;
		line-height: 1.5;
		display: block;
	}

	/* 代码查看器弹窗 */
	.code-viewer-popup {
		width: 90vw;
		max-width: 1200rpx;
		height: 85vh;
		background-color: #FFFFFF;
		border-radius: 20rpx;
		overflow: hidden;
		display: flex;
		flex-direction: column;
		transition: all 0.3s ease;
		
		/* 全屏模式 */
		&.fullscreen {
			width: 98vw;
			height: 95vh;
			max-width: none;
			border-radius: 12rpx;
		}
	}

	.code-viewer-popup .popup-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 30rpx;
		border-bottom: 1rpx solid #E5E5E5;
		background-color: #FAFAFA;

		.header-left {
			flex: 1;
			
			.popup-title {
				font-size: 32rpx;
				font-weight: 600;
				color: #333333;
			}
		}

		.header-actions {
			display: flex;
			align-items: center;
			gap: 30rpx;
		}

		.fullscreen-icon {
			display: flex;
			align-items: center;
			gap: 8rpx;
			padding: 10rpx 20rpx;
			background-color: #F0F0F0;
			border-radius: 8rpx;
			cursor: pointer;
			transition: background-color 0.2s;

			&:active {
				background-color: #E0E0E0;
			}

			.action-text {
				font-size: 26rpx;
				color: #666666;
				font-weight: 500;
			}
		}

		.copy-code-icon {
			display: flex;
			align-items: center;
			gap: 8rpx;
			padding: 10rpx 20rpx;
			background-color: #FFF5F5;
			border-radius: 8rpx;
			cursor: pointer;
			transition: background-color 0.2s;

			&:active {
				background-color: #FFE5E5;
			}

			.copy-text {
				font-size: 26rpx;
				color: #DB0000;
				font-weight: 500;
			}
		}
	}

	.code-viewer-content {
		flex: 1;
		overflow: hidden;
		display: flex;
		flex-direction: column;
	}

	.code-info-bar {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 20rpx 30rpx;
		background-color: #F7F7F7;
		border-bottom: 1rpx solid #E5E5E5;

		.code-file-name {
			font-size: 26rpx;
			color: #666666;
			font-family: 'Monaco', 'Courier New', monospace;
		}

		.code-size {
			font-size: 24rpx;
			color: #999999;
		}
	}

	.code-scroll {
		flex: 1;
		height: 0;
		background-color: #282c34;
	}

	.code-block {
		margin: 0;
		padding: 30rpx;
		font-size: 24rpx;
		line-height: 1.8;
		color: #abb2bf;
		font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
		white-space: pre-wrap;
		word-wrap: break-word;
		background-color: #282c34;
		overflow-x: auto;
	}

	/* 上传弹窗 */
	.upload-popup {
		width: 800rpx;
		background-color: #FFFFFF;
		border-radius: 20rpx;
		overflow: hidden;
	}

	.popup-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 30rpx;
		border-bottom: 1rpx solid #E5E5E5;

		.popup-title {
			font-size: 32rpx;
			font-weight: 500;
			color: #333333;
		}
	}

	.popup-content {
		padding: 40rpx;
		max-height: 1000rpx;
		overflow-y: auto;
	}

	.auth-tip {
		display: flex;
		align-items: center;
		gap: 10rpx;
		padding: 20rpx;
		background-color: #fffbe6;
		border-radius: 8rpx;
		margin-bottom: 20rpx;

		.tip-text {
			flex: 1;
			font-size: 24rpx;
			color: #666666;
			line-height: 1.5;
		}

		&.success {
			background-color: #f6ffed;
		}
	}

	.form-item {
		margin-bottom: 30rpx;

		.form-label {
			display: block;
			font-size: 28rpx;
			color: #333333;
			margin-bottom: 16rpx;
		}

		.form-input {
			width: 100%;
			height: 80rpx;
			background-color: #F7F7F7;
			border-radius: 8rpx;
			padding: 0 20rpx;
			font-size: 28rpx;
		}

		.form-textarea {
			width: 100%;
			min-height: 150rpx;
			background-color: #F7F7F7;
			border-radius: 8rpx;
			padding: 20rpx;
			font-size: 28rpx;
		}
		
		.form-tip {
			display: block;
			font-size: 22rpx;
			color: #999999;
			margin-top: 10rpx;
			line-height: 1.5;
			
			&.warning {
				color: #faad14;
				font-weight: 500;
			}
		}
		
		.file-name-input-wrapper {
			display: flex;
			align-items: center;
			background-color: #F7F7F7;
			border-radius: 8rpx;
			overflow: hidden;
			
			.file-name-input {
				flex: 1;
				height: 80rpx;
				padding: 0 20rpx;
				font-size: 28rpx;
			}
			
			.file-extension {
				padding: 0 20rpx;
				font-size: 28rpx;
				color: #999999;
				background-color: #EEEEEE;
				height: 80rpx;
				display: flex;
				align-items: center;
			}
		}

		.category-selector {
			display: flex;
			align-items: center;
			justify-content: space-between;
			height: 80rpx;
			background-color: #F7F7F7;
			border-radius: 8rpx;
			padding: 0 20rpx;

			.selector-text {
				font-size: 28rpx;
				color: #333333;

				&.placeholder {
					color: #CCCCCC;
				}
			}
		}

		.code-upload-btn {
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 10rpx;
			height: 120rpx;
			background-color: #F7F7F7;
			border-radius: 8rpx;
			border: 2rpx dashed #CCCCCC;

			.code-file-name {
				font-size: 26rpx;
				color: #333333;
			}

			.placeholder-text {
				font-size: 26rpx;
				color: #999999;
			}
		}
	}

	.popup-footer {
		display: flex;
		gap: 20rpx;
		padding: 30rpx;
		border-top: 1rpx solid #E5E5E5;
	}

	/* 分类列表弹窗 */
	.category-list-overlay {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(0, 0, 0, 0.5);
		z-index: 10001;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.category-list-content {
		width: 500rpx;
		max-height: 80vh;
		background-color: #FFFFFF;
		border-radius: 12rpx;
		overflow: hidden;
		display: flex;
		flex-direction: column;
	}

	.category-list-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 30rpx;
		border-bottom: 1rpx solid #E5E5E5;

		.category-list-title {
			font-size: 32rpx;
			font-weight: 500;
			color: #333333;
		}
	}

	.category-list-scroll {
		max-height: 400rpx;
		overflow-y: auto;
	}

	.category-list-item {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 30rpx;
		border-bottom: 1rpx solid #F5F5F5;

		&:active {
			background-color: #F7F7F7;
		}

		.category-list-name {
			flex: 1;
			font-size: 30rpx;
			color: #333333;
		}
	}

	.add-category-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 10rpx;
		padding: 30rpx;
		border-top: 2rpx solid #E5E5E5;
		background-color: #FAFAFA;

		&:active {
			background-color: #F0F0F0;
		}

		.add-category-text {
			font-size: 28rpx;
			color: #DB0000;
			font-weight: 500;
		}
	}

	/* 新增分类弹窗 */
	.add-category-popup {
		width: 600rpx;
		background-color: #FFFFFF;
		border-radius: 20rpx;
		overflow: hidden;
	}

	.icon-grid {
		display: grid;
		grid-template-columns: repeat(4, 1fr);
		gap: 20rpx;
		margin-top: 10rpx;
	}

	.icon-item {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 20rpx;
		border-radius: 8rpx;
		border: 2rpx solid #E5E5E5;
		background-color: #FAFAFA;

		&.active {
			border-color: #DB0000;
			background-color: #FFF5F5;
		}

		.icon-label {
			font-size: 22rpx;
			color: #666666;
			margin-top: 10rpx;
		}
	}
</style>

